package gat.application.tg.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bitsun.core.common.exception.AppException;
import com.bitsun.core.common.exception.ErrorCode;
import com.bitsun.core.common.persistence.BasePService;
import com.bitsun.core.common.persistence.IPService;
import com.bitsun.core.common.persistence.Pager;
import com.bitsun.core.common.persistence.QueryParamUtils;
import com.google.common.base.CaseFormat;
import gat.application.tg.TopupPriceService;
import gat.common.util.CurrentThread;
import gat.convertor.tg.TopupPriceReqDtoConvertor;
import gat.convertor.tg.TopupPriceResDtoConvertor;
import gat.dto.req.tg.TopupPriceReqDto;
import gat.dto.req.tg.TopupPriceReqParams;
import gat.dto.res.tg.TopupPriceResDto;
import gat.dto.res.tg.UserBotResDto;
import gat.infrastructure.persistence.dao.tg.TopupPriceMapper;
import gat.infrastructure.persistence.po.tg.TgBotPo;
import gat.infrastructure.persistence.po.tg.TopupPricePo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
 * 示例表，应用（业务编排）层实现
 * @author: yanshukeji-java
 * @email: yanshukeji-java
 */
@Slf4j
@Service("topupPriceAppService")
@Transactional(rollbackFor = Exception.class)
public class TopupPriceServiceImpl implements TopupPriceService {

    @Autowired
    private TopupPriceReqDtoConvertor topupPriceReqDtoConvertor;

    @Autowired
    private TopupPriceResDtoConvertor topupPriceResDtoConvertor;

    private IPService<TopupPricePo> topupPricePoService;

    @SuppressWarnings("SpringJavaAutowiringInspection")
    public TopupPriceServiceImpl(TopupPriceMapper topupPriceMapper) {
        this.topupPricePoService = new BasePService(topupPriceMapper);
    }

    @Override
    public TopupPriceResDto save(TopupPriceReqDto reqDto) {
        if (reqDto.getType() == 2 && StringUtils.isEmpty(reqDto.getBotId())) {
            throw new AppException("专属机器人类型必须填写机器人ID", ErrorCode.pc("417"));
        }

        // 校验默认类型不能有botId
        if (reqDto.getType() == 1 && !StringUtils.isEmpty(reqDto.getBotId())) {
            throw new AppException("默认类型不能关联机器人ID", ErrorCode.pc("417"));
        }

        boolean exists;
        if (reqDto.getType() == 1) {
            // 默认类型检查
            TopupPricePo topupPricePo = topupPricePoService.getOne(new LambdaQueryWrapper<TopupPricePo>()
                    .eq(TopupPricePo::getType, 1)
                    .eq(TopupPricePo::getPrice, reqDto.getPrice())
            );
            if (topupPricePo == null) {
                exists = false;
            } else {
                exists = true;
            }
        } else {
            // 专属机器人类型检查
            TopupPricePo topupPricePo = topupPricePoService.getOne(new LambdaQueryWrapper<TopupPricePo>()
                    .eq(TopupPricePo::getType, 2)
                    .eq(TopupPricePo::getPrice, reqDto.getPrice())
                    .eq(TopupPricePo::getBotId, reqDto.getBotId())
            );
            if (topupPricePo == null) {
                exists = false;
            } else {
                exists = true;
            }
        }

        if (exists) {
            throw new AppException("该类型下已存在相同价格的配置");
        }

        TopupPricePo po = topupPriceReqDtoConvertor.dto2Po(reqDto);
        topupPricePoService.save(po);
        TopupPriceResDto resDto = topupPriceResDtoConvertor.po2Dto(po);
        return resDto;
    }

    @Override
    public boolean deleteByIds(String ids) {
        try {
            List<Long> idLongList =
            Arrays.asList(ids.split(",")).stream().map(s -> NumberUtils.createLong(s.trim())).collect(Collectors.toList());
            return topupPricePoService.removeByIds(idLongList);
        } catch (Exception e) {
            throw new AppException("参数错误：" + ids, ErrorCode.pc("417"), e);
        }
     }

    @Override
    public Pager<TopupPriceResDto> doPager(Map<String, Object> params) {
        Pager<TopupPricePo> poPager = topupPricePoService.queryPage(params, TopupPricePo.class);
        Pager<TopupPriceResDto> resDtoPager = topupPriceResDtoConvertor.convertPoPager2ResDtoPager(poPager);
        return resDtoPager;
    }

    @Override
    public TopupPriceResDto selectOne(Long id) {
        TopupPricePo po = topupPricePoService.getById(id);
        TopupPriceResDto resDto = topupPriceResDtoConvertor.po2Dto(po);
        return resDto;
    }

    @Override
    public TopupPriceResDto selectOne(Map<String, Object> params) {
        QueryWrapper queryWrapper = QueryParamUtils.queryWrapper4eq(TopupPricePo::new, params);
        queryWrapper.last(" limit 1");
        TopupPricePo po = topupPricePoService.getOne(queryWrapper);
        TopupPriceResDto resDto = topupPriceResDtoConvertor.po2Dto(po);
        return resDto;
    }

    @Override
    public boolean updateProps(Long id, Map<String, Object> params) {
        UpdateWrapper<TopupPricePo> updateWrapper = QueryParamUtils.updateWrapper4Map(TopupPricePo::new, id, params);
        return topupPricePoService.update(new TopupPricePo(), updateWrapper);
        }

    @Override
    public boolean updateProps(Long id, TopupPriceReqDto reqDto) {
        TopupPricePo po = topupPriceReqDtoConvertor.dto2Po(reqDto);
        po.setId(id);

        TopupPricePo topupPricePo = topupPricePoService.getById(id);
        // 更新允许修改的字段
        if (reqDto.getPrice() != null) {
            // 检查新价格是否与同类型其他配置冲突
            boolean priceConflict = false;
            if (topupPricePo.getType() == 1) {
                TopupPricePo topupPricePo1 = topupPricePoService.getOne(new LambdaQueryWrapper<TopupPricePo>()
                        .eq(TopupPricePo::getType, 1)
                        .eq(TopupPricePo::getPrice, reqDto.getPrice())
                );
                if (topupPricePo1 != null && !topupPricePo1.getId().equals(id)) {
                    priceConflict = true;
                }
            } else {
                TopupPricePo topupPricePo1 = topupPricePoService.getOne(new LambdaQueryWrapper<TopupPricePo>()
                        .eq(TopupPricePo::getType, 2)
                        .eq(TopupPricePo::getPrice, reqDto.getPrice())
                        .eq(TopupPricePo::getBotId, reqDto.getBotId())
                );
                if (topupPricePo1 != null && !topupPricePo1.getId().equals(id)) {
                    priceConflict = true;
                }
            }
            if (priceConflict) {
                throw new AppException("该类型下已存在相同价格的配置");
            }
        }
        return topupPricePoService.updateById(po);
    }


    @Override
    public boolean updateAllProps(Long id, TopupPriceReqDto reqDto) {
        UpdateWrapper<TopupPricePo> updateWrapper = Wrappers.update();
        updateWrapper.eq("id", id);
        Field[] fields = TopupPriceReqDto.class.getDeclaredFields();
        Arrays.stream(fields).filter(f -> !Modifier.isStatic(f.getModifiers())).forEach(field -> {
        try {
        PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), TopupPriceReqDto.class);
        Method getMethod = propertyDescriptor.getReadMethod();
        String fileNameCamel = getMethod.getName().substring(3);
        String fileNameUnderline = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, fileNameCamel);
        updateWrapper.set(fileNameUnderline, getMethod.invoke(reqDto));
        } catch (Exception ex) {
        log.warn("属性不存在get方法："+field.getName(),ex);
        }
        });
        return topupPricePoService.update(new TopupPricePo(), updateWrapper);
    }

    @Override
    public Pager<TopupPriceResDto> queryPage(TopupPriceReqParams params) {

        String username = CurrentThread.getCurrentUser().getUsername();
        if (!StringUtils.equals(username, "admin") && StringUtils.isEmpty(params.getBotId())) {
            throw new AppException("参数错误：机器人id不能为空");
        }

        IPage<TopupPricePo> iPage =
                topupPricePoService.page(new Page<>(params.getCurrentPage(), params.getPageSize()),
                        new LambdaQueryWrapper<TopupPricePo>()
                                .eq(StringUtils.isNotBlank(params.getBotId()), TopupPricePo::getBotId, params.getBotId())
                                .eq(ObjectUtil.isNotEmpty(params.getPriceStatus()), TopupPricePo::getPriceStatus, params.getPriceStatus())
                                .eq(ObjectUtil.isNotEmpty(params.getType()), TopupPricePo::getType, params.getType())
                                .orderByDesc(TopupPricePo::getCreateTime)
                );
        return topupPriceResDtoConvertor.convertPoPager2ResDtoPager(
                new Pager<>(iPage.getRecords(), iPage.getTotal(), params.getPageSize(), iPage.getCurrent()));
    }

}